/*-------------------------------------------------------------------------
 *
 * fe-auth-sasl.h
 *	  定义了 libpq 的 SASL 机制接口。
 *
 * 每个 SASL 机制定义一个前端和一个后端回调结构。
 * 这不是应用程序的公共 API 的一部分。
 *
 * 请参阅 src/include/libpq/sasl.h 以获取后端对应部分。
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * src/interfaces/libpq/fe-auth-sasl.h
 *
 *-------------------------------------------------------------------------
 */

#ifndef FE_AUTH_SASL_H
#define FE_AUTH_SASL_H

#include "libpq-fe.h"

/*
 * 前端 SASL 机制回调。
 *
 * 要实现前端机制，请声明一个 pg_be_sasl_mech 结构体，并提供
 * 适当的回调实现，然后在 pg_SASL_init() 的机制协商中将其挂钩到 conn->sasl。
 */
typedef struct pg_fe_sasl_mech
{
	/*-------
	 * init()
	 *
	 * 为连接初始化机制特定状态。此回调必须返回指向其分配状态的指针，
	 * 该指针将作为其他回调的第一个参数原样传递。
	 * free() 回调被调用以释放任何状态资源。
	 *
	 * 如果状态分配失败，实现在此情况下应返回 NULL 来使身份验证交换失败。
	 *
	 * 输入参数：
	 *
	 *   conn:     连接到服务器
	 *
	 *   password: 用户为当前连接提供的密码
	 *
	 *   mech:     正在使用的机制名称，适用于可能
	 *			   宣传多个名称的实现（例如 *-PLUS 变体）。
	 *-------
	 */
	void	   *(*init) (PGconn *conn, const char *password, const char *mech);

	/*--------
	 * exchange()
	 *
	 * 产生客户端对服务器挑战的响应。作为客户端优先 SASL 机制的特例，
	 * exchange() 在身份验证交换开始时以 NULL 服务器响应被调用一次，以生成初始响应。
	 *
	 * 输入参数：
	 *
	 *	state:	   init() 返回的不透明机制状态
	 *
	 *	input:	   服务器发送的挑战数据，或在生成客户端优先初始响应时为 NULL
	 *			   （即，服务器期望客户端发送消息以启动交换）。为安全起见，这保证是以 null 结尾的，
	 *			   但 SASL 允许在挑战中嵌入 null，因此机制必须小心检查 inputlen。
	 *
	 *	inputlen:  服务器发送的挑战数据的长度，或在生成客户端优先初始响应时为 -1。
	 *
	 * 输出参数，由回调函数设置：
	 *
	 *	output:	   一个 malloc 申请的缓冲区，包含客户端对
	 *			   服务器的响应（可以为空），或 NULL 如果交换应该
	 *			   被中止。 （在后一种情况下，*success 应设置为 false。）
	 *
	 *	outputlen: 客户端响应缓冲区的长度（0 或更高），
	 *			   如果 output 为 NULL，则忽略。
	 *
	 *	done:      如果 SASL 交换不应继续，则设置为 true，
	 *			   因为交换要么完成，要么失败
	 *
	 *	success:   如果 SASL 交换成功完成，则设置为 true。
	 *			   如果 *done 为 false，则忽略。
	 *--------
	 */
	void		(*exchange) (void *state, char *input, int inputlen,
							 char **output, int *outputlen,
							 bool *done, bool *success);

	/*--------
	 * channel_bound()
	 *
	 * 如果连接具有已建立的通道绑定，则返回 true。机制实现必须确保 SASL 交换确实
	 * 已完成，除此之外还需检查通道绑定是否在使用。
	 *
	 * 不实现通道绑定的机制可以简单返回 false。
	 *
	 * 输入参数：
	 *
	 *	state:    init() 返回的不透明机制状态
	 *--------
	 */
	bool		(*channel_bound) (void *state);

	/*--------
	 * free()
	 *
	 * 释放由 init() 分配的状态。在连接断开时调用，而不是在交换完成时。
	 *
	 * 输入参数：
	 *
	 *   state:    由 init() 返回的不透明机制状态
	 *--------
	 */
	void		(*free) (void *state);

} pg_fe_sasl_mech;

#endif							/* FE_AUTH_SASL_H */
